package asteroids.components;

import com.uqbar.vainilla.DeltaState;
import com.uqbar.vainilla.appearances.Sprite;
import com.uqbar.vainilla.events.constants.Key;

public class SpaceShip extends AbstractAsteroidsGameComponent {
	
	private double acceleration = 0;
	private double deceleration = 0;
	
	private static int GAME_HEIGHT;
	private static int GAME_WIDTH;
	
	private static final double MAX_SPEED         = 15;
	private static final double MIN_SPEED         = 1;
	private static final double MAX_ACCELERATION  = 5;
	private static final double MIN_ACCELERATION  = 0;
	private static final double ACCELERATION_RATE = 0.0005;
	private static final double DECELERATION_BASE = 0;
	private static final double DECELERATION_RATE = 0.00045;
	private static final double RADIANS_TO_DEGREE = 0.02;

	public SpaceShip() {
		this.setSpeed(MIN_SPEED);
		this.setAndRotateSprite(0);
	}
	
	private void setAndRotateSprite(double inclination) {
		this.setAppearance(Sprite.fromImage("/images/ship.png").crop(5, 5, 80, 80).rotate(inclination));
	}
	
	@Override
	public void onSceneActivated() {
		GAME_WIDTH  = this.getGame().getDisplayWidth();
		GAME_HEIGHT = this.getGame().getDisplayHeight();
		
		this.setX(GAME_WIDTH / 2);
		this.setY(GAME_HEIGHT / 2);
		
		super.onSceneActivated();
	}
	
	private void moveAngularly(double radians) {
		this.setDirection(this.getDirection() + radians);
		this.setAndRotateSprite(-this.getDirection());
		this.setVersorI(Math.sin(this.getDirection()));
		this.setVersorJ(Math.cos(this.getDirection()));
	}
	
	@Override
	public void update(DeltaState deltaState) {
		
		if (deltaState.isKeyBeingHold(Key.UP))
			accelerate(ACCELERATION_RATE);
		
		if (!deltaState.isKeyBeingHold(Key.UP))
			decelerate(DECELERATION_RATE);
		
		if (deltaState.isKeyBeingHold(Key.LEFT))
			this.moveAngularly(RADIANS_TO_DEGREE);
			
		if (deltaState.isKeyBeingHold(Key.RIGHT))
			this.moveAngularly(-RADIANS_TO_DEGREE);
		
		if (deltaState.isKeyPressed(Key.Z)) {
			double shooterX = this.getX() + this.getAppearance().getWidth() / 2 - 4 - ((this.getAppearance().getWidth() / 2 - 2) * this.getVersorI());
			double shooterY = this.getY() + this.getAppearance().getHeight() / 2 - 2 - ((this.getAppearance().getHeight() / 2 - 3) * this.getVersorJ());
			this.getScene().addOneBulletToGame(shooterX, shooterY, this);
		}
		
		super.update(deltaState);
	}

	private void accelerate(double rate) {
		if (this.getSpeed() < MAX_SPEED && this.getAcceleration() < MAX_ACCELERATION) {
			this.setAcceleration(this.getAcceleration() + rate);
			this.setSpeed(this.getSpeed() + this.getAcceleration());
		}
		else {
			this.setSpeed(MAX_SPEED);
		}
		this.move(-this.getSpeed() * this.getVersorI(), -this.getSpeed() * this.getVersorJ());
	}

	private void decelerate(double rate) {
		if (this.getSpeed() > MIN_SPEED && this.getAcceleration() > MIN_ACCELERATION) {
			this.setDeceleration(this.getDeceleration() + rate);
			this.setSpeed(this.getSpeed() - this.getDeceleration());
			this.move(-this.getSpeed() * this.getVersorI(), -this.getSpeed() * this.getVersorJ());
		}
		else {
			this.setSpeed(MIN_SPEED);
			this.setAcceleration(MIN_ACCELERATION);
			this.setDeceleration(DECELERATION_BASE);
		}
	}
	
	public void explode() {
		if (!this.isDestroyPending())
			this.getScene().explodeShip();
	}
	
	
	

	public double getAcceleration() {
		return acceleration;
	}

	public void setAcceleration(double acceletarion) {
		this.acceleration = acceletarion;
	}

	public double getDeceleration() {
		return deceleration;
	}

	public void setDeceleration(double deceleration) {
		this.deceleration = deceleration;
	}
}
